﻿using System;
using System.Management.Automation;

namespace BO.Management.PowerShell
{
    /// <summary>
    /// Base Cmdlet to manage BO. This class offers infrastructure to connect to BO
    /// </summary>
    [CmdletBinding(DefaultParameterSetName = CONNECT_SECWINAD)]
    public abstract class BaseBOECmdlet : Cmdlet
    {

        #region "Private members"
        private CrystalDecisions.Enterprise.EnterpriseSession _session;
        private String _sessionToken;
        private String _userName;
        private String _password;
        private String _cmsName;


        internal const String CONNECT_INLINE_SESSION = "Inline Session";
        internal const String CONNECT_TOKEN_SESSION = "Token Session";
        internal const String CONNECT_SECENTERPRISE = "SecEnterprise";
        internal const String CONNECT_SECWINAD = "SecWinAD";
        #endregion


        #region "Properties"
        //[Parameter(Position = 0, ParameterSetName = CONNECT_INLINE_SESSION, Mandatory = true,
        //           ValueFromPipeline = true, ValueFromPipelineByPropertyName = true)]
        //[ValidateNotNullOrEmpty]
        public CrystalDecisions.Enterprise.EnterpriseSession Session
        {
            get { return _session; }
            set { _session = value; }
        }

        //[Parameter(Position = 0, ParameterSetName = CONNECT_TOKEN_SESSION, Mandatory = true,
        //           ValueFromPipeline = true, ValueFromPipelineByPropertyName = true)]
        //[ValidateNotNullOrEmpty]
        public String SessionToken
        {
            get { return _sessionToken; }
            set { _sessionToken = value; }
        }

        [Parameter(Position = 1, ParameterSetName = CONNECT_SECENTERPRISE, Mandatory = true)]
        [ValidateNotNullOrEmpty]
        public string UserName
        {
            get { return _userName; }
            set { _userName = value; }
        }

        [Parameter(Position = 2, ParameterSetName = CONNECT_SECENTERPRISE, Mandatory = false)]
        public string Password
        {
            get { return _password; }
            set { _password = value; }
        }

        [Parameter(Position = 0)]
        [ValidateNotNullOrEmpty]
        public string cmsName
        {
            get { return _cmsName; }
            set { _cmsName = value; }
        }

        #endregion


        internal LogonProvider LogonProvider
        {
            get;
            set;
        }


        protected override void BeginProcessing()
        {
            base.BeginProcessing();
            this.LogonProvider = new LogonProvider();
        }

        protected override void EndProcessing()
        {
            if (this.LogonProvider != null)
            {
                if (this.LogonProvider.Session.IsServerLogonSession()) this.LogonProvider.Session.Logoff();
                this.LogonProvider.Dispose();
            }
            base.EndProcessing();
        }

        protected override void ProcessRecord()
        {
            base.ProcessRecord();
            CrystalDecisions.Enterprise.EnterpriseSession session = null;

            try
            {
                session = this.GetSession(this.LogonProvider);
            }
            catch (Exception ex)
            {
                this.ThrowTerminatingErrorWithExitCode(BOErrorCode.OpenCmsSession, "Error when opening a new CMS session", ex);
            }

            if (session == null)
            {
                this.ThrowTerminatingErrorWithExitCode(BOErrorCode.OpenCmsSession, "Unable to get connection to the BOE infrastructure");
            }


        }

        /// <summary>
        /// Get a BO session to use management powershell.
        /// </summary>
        /// <returns></returns>
        internal CrystalDecisions.Enterprise.EnterpriseSession GetSession(LogonProvider logonProvider)
        {
            if (this.Session != null)
            {
                WriteVerbose("Connection mode : " + CONNECT_INLINE_SESSION);
                return this.Session;
            }

            if (!String.IsNullOrEmpty(this.SessionToken))
            {
                WriteVerbose("Connection mode : " + CONNECT_TOKEN_SESSION);
                return logonProvider.LogonWithToken(this.SessionToken);
            }

            if (!String.IsNullOrEmpty(this.UserName) && !String.IsNullOrEmpty(this.cmsName))
            {
                WriteVerbose("Connection mode : " + CONNECT_SECENTERPRISE);
                return logonProvider.Logon(this.UserName, this.Password, this.cmsName);
            }
            else
            {
                WriteVerbose("Connection mode : " + CONNECT_SECWINAD);
                return logonProvider.Logon(this.cmsName);
            }
        }


        internal void ThrowTerminatingErrorWithExitCode(BOErrorCode errorCode, String message)
        {
            this.ThrowTerminatingErrorWithExitCode(errorCode, message, null);
        }

        internal void ThrowTerminatingErrorWithExitCode(BOErrorCode errorCode, String message, Exception innerException)
        {
            Int32 exitCode = (Int32)errorCode;

            ErrorRecord error = BOErrorManagement.GetErrorRecord(errorCode, message, innerException);
            //this.CommandRuntime.Host.SetShouldExit(exitCode);
            this.ThrowTerminatingError(error);

        }

    }
}
